// plagiarism_core/static/js/report.js

document.addEventListener('DOMContentLoaded', function () {
    const urlParams = new URLSearchParams(window.location.search);
    const taskId = urlParams.get('task_id');
    const plagiarismApiBaseUrl = "http://127.0.0.1:5055/plagiarism"; // 或者从配置传入

    if (taskId) {
        fetchReportData(taskId, plagiarismApiBaseUrl);
    } else {
        displayError("错误：URL中未提供 task_id。");
        // 或者可以显示一个提示用户如何使用的信息
        // document.body.innerHTML = "<h1>请在URL中提供task_id参数，例如：report_template.html?task_id=YOUR_TASK_ID</h1>";
    }
});

function displayError(message) {
    const errorArea = document.getElementById('error-message-area');
    const errorContent = document.getElementById('error-message-content');
    if (errorArea && errorContent) {
        errorContent.textContent = message;
        errorArea.classList.remove('hidden');
        // 隐藏其他可能显示“加载中”的部分
        const allCards = document.querySelectorAll('.card-container');
        allCards.forEach(card => {
            if (!card.id || card.id !== 'error-message-area') {
                // card.classList.add('hidden'); // 根据需要决定是否隐藏其他卡片
            }
        });
    } else {
        alert(message); // Fallback
    }
    // 停止所有可能的加载指示
    document.querySelectorAll('.info-card__value, .summary-card__stat-value, .stats-card__cell--content, .highlight-content, #source-analysis-list li, #results-placeholder')
        .forEach(el => {
            if (el.textContent.includes("加载中...")) el.textContent = "错误";
        });
}


async function fetchReportData(taskId, apiBaseUrl) {
    const apiUrl = `${apiBaseUrl}/get_report_data/${taskId}`;
    console.log("Fetching report data from:", apiUrl);

    try {
        const response = await fetch(apiUrl);
        if (!response.ok) {
            const errorData = await response.json().catch(() => null);
            throw new Error(`API请求失败，状态码: ${response.status}. ${errorData ? errorData.error : response.statusText}`);
        }
        const result = await response.json();

        if (result.success && result.report_data) {
            console.log("Report data received:", result);
            populateReport(result.report_data, result.cleaned_input_text);
            // 如果有错误信息也显示
            if (result.report_data.error_message) {
                displayError(`后端处理时发生错误: ${result.report_data.error_message}`);
            }
        } else {
            throw new Error(result.error || "从API获取报告数据失败或数据格式不正确。");
        }
    } catch (error) {
        console.error("获取报告数据时出错:", error);
        displayError(`加载报告数据失败: ${error.message}`);
    }
}

function populateReport(data, cleanedInputText) {
    const taskInfo = data.task_info || {};
    const textStats = data.text_stats || {};
    const aggMetrics = data.aggregate_metrics || {};

    // 1. 填充基本信息
    document.getElementById('info-task-id').textContent = taskInfo.task_id || 'N/A';
    document.getElementById('info-check-time').textContent = taskInfo.check_time || 'N/A';
    document.getElementById('info-original-filename').textContent = taskInfo.original_filename || 'N/A';
    document.getElementById('info-processing-time').textContent = taskInfo.processing_time_seconds !== undefined ? `${taskInfo.processing_time_seconds.toFixed(2)} 秒` : 'N/A';


    // 2. 填充摘要卡片
    document.getElementById('summary-overall-ratio').textContent = formatPercentage(aggMetrics.overall_similarity_ratio);
    document.getElementById('summary-max-single-ratio').textContent = formatPercentage(aggMetrics.max_similarity_ratio_single_source);
    document.getElementById('summary-duplicate-chars').textContent = aggMetrics.duplicate_chars_count !== undefined ? aggMetrics.duplicate_chars_count : 'N/A';


    // 3. 填充详细统计 (使用ID匹配)
    const statsMap = {
        "stats-overall-ratio": formatPercentage(aggMetrics.overall_similarity_ratio),
        "stats-total-paragraphs": textStats.total_paragraphs,
        "stats-max-single-ratio": formatPercentage(aggMetrics.max_similarity_ratio_single_source),
        "stats-front-overlap": aggMetrics.front_part_overlap_chars,
        "stats-duplicate-chars": aggMetrics.duplicate_chars_count,
        "stats-rear-overlap": aggMetrics.rear_part_overlap_chars,
        "stats-total-chars": textStats.total_chars,
        "stats-suspected-para-count": aggMetrics.suspected_paragraph_count,
        "stats-max-single-chars": aggMetrics.max_duplicate_chars_single_source,
        "stats-max-para-chars": aggMetrics.max_duplicate_chars_in_paragraph,
        "stats-semantic-hit-count": aggMetrics.semantic_hit_block_count,
        "stats-min-para-chars": aggMetrics.min_duplicate_chars_in_paragraph,
        "stats-total-words": textStats.total_words,
        "stats-compared-docs": textStats.compared_doc_count,
        "stats-max-semantic-score": aggMetrics.max_semantic_score !== undefined ? aggMetrics.max_semantic_score.toFixed(4) : 'N/A',
        "stats-max-ngram-score": aggMetrics.max_ngram_score !== undefined ? aggMetrics.max_ngram_score.toFixed(4) : 'N/A',
        // 确保所有在 AggregateMetrics 和 TextStats 中定义的字段都有对应的HTML ID和在此处的映射
    };

    for (const id in statsMap) {
        const element = document.getElementById(id);
        if (element) {
            const value = statsMap[id];
            element.textContent = (value !== undefined && value !== null) ? value : 'N/A';
        } else {
            console.warn(`populateReport: Stats element with ID '${id}' not found in HTML.`);
        }
    }


    // 4. 填充来源分析
    populateSourceAnalysis(aggMetrics, data.hit_details_by_source, textStats.total_chars);

    // 5. 填充命中结果列表
    populateHitResults(data.hit_details_by_source, textStats.total_chars, cleanedInputText ? cleanedInputText.length : 0);

    // 6. 生成并填充高亮原文
    if (cleanedInputText) {
        const literalHtml = generateHighlightedTextHtml(cleanedInputText, data.hit_details_by_source, 'literal');
        document.getElementById('highlight-content-literal').innerHTML = literalHtml;

        const semanticHtml = generateHighlightedTextHtml(cleanedInputText, data.hit_details_by_source, 'semantic');
        document.getElementById('highlight-content-semantic').innerHTML = semanticHtml;
    } else {
        document.getElementById('highlight-content-literal').innerHTML = '<p style="color:grey;">原文缺失，无法生成高亮显示。</p>';
        document.getElementById('highlight-content-semantic').innerHTML = '<p style="color:grey;">原文缺失，无法生成高亮显示。</p>';
    }
}

function formatPercentage(value) {
    if (typeof value === 'number') {
        return `${value.toFixed(2)}%`;
    }
    return 'N/A';
}

function escapeHtml(unsafe) {
    if (unsafe === null || unsafe === undefined) return '';
    return String(unsafe)
        .replace(/&/g, "&amp;")
        .replace(/</g, "&lt;")
        .replace(/>/g, "&gt;")
        .replace(/"/g, "&quot;")
        .replace(/'/g, "&#39;");
}


function populateSourceAnalysis(aggMetrics, hitDetailsBySource, totalInputChars) {
    const listElement = document.getElementById('source-analysis-list');
    listElement.innerHTML = ''; // Clear "加载中..."

    if (!hitDetailsBySource || Object.keys(hitDetailsBySource).length === 0) {
        listElement.innerHTML = `<li class="source-analysis-card__item flex-row">
            <div class="source-analysis-card__item-marker flex-col" style="background-color: green;"></div>
            <span class="source-analysis-card__item-text">未检测到有效重复来源</span>
        </li>`;
        return;
    }

    const sourceRatios = [];
    for (const sourceFile in hitDetailsBySource) {
        let sourceLiteralCharsSet = new Set();
        const hits = hitDetailsBySource[sourceFile];
        if (Array.isArray(hits)) {
            hits.forEach(hit => {
                if (hit.match_type === 'literal' && hit.input_fragment) {
                    const start = hit.input_fragment.start_char;
                    const end = hit.input_fragment.end_char;
                    if (typeof start === 'number' && typeof end === 'number' && start < end) {
                        for (let i = start; i < end; i++) {
                            sourceLiteralCharsSet.add(i);
                        }
                    }
                }
            });
        }
        const ratio = totalInputChars > 0 ? (sourceLiteralCharsSet.size / totalInputChars) * 100 : 0;
        sourceRatios.push({ source_file: sourceFile, ratio: ratio });
    }

    sourceRatios.sort((a, b) => b.ratio - a.ratio);

    // 从配置或默认值获取报告参数 (这些应该从后端API获取，或者在JS中定义默认值)
    const maxSourcesToShow = 5; // aggMetrics.REPORT_MAX_SOURCES_IN_ANALYSIS || 5;
    const highThresh = 40.0; // aggMetrics.REPORT_RATIO_THRESHOLD_HIGH || 40.0;
    const medThresh = 10.0; // aggMetrics.REPORT_RATIO_THRESHOLD_MEDIUM || 10.0;
    const colorHigh = 'red'; // aggMetrics.REPORT_COLOR_HIGH || 'red';
    const colorMed = 'orange'; // aggMetrics.REPORT_COLOR_MEDIUM || 'orange';
    const colorLow = 'yellow'; // aggMetrics.REPORT_COLOR_LOW || 'yellow';
    const colorZero = '#ccc'; // aggMetrics.REPORT_COLOR_ZERO || '#ccc';


    sourceRatios.slice(0, maxSourcesToShow).forEach((item, index) => {
        let bgColor = colorZero;
        if (item.ratio >= highThresh) bgColor = colorHigh;
        else if (item.ratio >= medThresh) bgColor = colorMed;
        else if (item.ratio > 0) bgColor = colorLow;

        const li = document.createElement('li');
        li.className = 'source-analysis-card__item flex-row';
        li.innerHTML = `
            <div class="source-analysis-card__item-marker flex-col" style="background-color: ${bgColor};"></div>
            <span class="source-analysis-card__item-text">
                ${index + 1}. ${escapeHtml(item.source_file)}：文字复制比 ${item.ratio.toFixed(2)}%
            </span>
        `;
        listElement.appendChild(li);
    });
    if (sourceRatios.length === 0) { // 双重检查，如果计算后 ratios 仍为空
        listElement.innerHTML = `<li class="source-analysis-card__item flex-row">
            <div class="source-analysis-card__item-marker flex-col" style="background-color: green;"></div>
            <span class="source-analysis-card__item-text">未计算出有效来源复制比</span>
        </li>`;
    }
}


function populateHitResults(hitDetailsBySource, totalInputChars, textLen) {
    const resultsContainer = document.getElementById('results-card-container');
    const placeholder = document.getElementById('results-placeholder');
    if (placeholder) placeholder.remove(); // 移除 "加载中..."

    if (!hitDetailsBySource || Object.keys(hitDetailsBySource).length === 0) {
        const noHitsP = document.createElement('p');
        noHitsP.style.textAlign = 'center';
        noHitsP.style.color = 'grey';
        noHitsP.style.marginTop = '20px';
        noHitsP.textContent = '未检测到任何相似内容。';
        resultsContainer.appendChild(noHitsP);
        return;
    }

    // 计算每个来源的字面复制比用于排序
    const sourceMetrics = [];
    for (const sourceFile in hitDetailsBySource) {
        let sourceLiteralCharsSet = new Set();
        let literalHitCount = 0;
        let semanticHitCount = 0;
        const hits = hitDetailsBySource[sourceFile];

        if (Array.isArray(hits)) {
            hits.forEach(hit => {
                if (hit.match_type === 'literal') {
                    literalHitCount++;
                    if (hit.input_fragment) {
                        const start = hit.input_fragment.start_char;
                        const end = hit.input_fragment.end_char;
                        if (typeof start === 'number' && typeof end === 'number' && start < end) {
                            for (let i = start; i < end; i++) sourceLiteralCharsSet.add(i);
                        }
                    }
                } else if (hit.match_type === 'semantic') {
                    semanticHitCount++;
                }
            });
        }
        const ratio = totalInputChars > 0 ? (sourceLiteralCharsSet.size / totalInputChars) * 100 : 0;
        sourceMetrics.push({
            source_file: sourceFile,
            ratio: ratio,
            literal_char_count: sourceLiteralCharsSet.size,
            literal_hits: literalHitCount,
            semantic_hits: semanticHitCount,
            all_hits_for_source: hits.sort((a, b) => (a.input_fragment.start_char || 0) - (b.input_fragment.start_char || 0)) // 按原文位置排序
        });
    }

    sourceMetrics.sort((a, b) => b.ratio - a.ratio); // 按复制比降序

    let itemIndex = 1;
    sourceMetrics.forEach(metric => {
        const resultItemDiv = document.createElement('div');
        resultItemDiv.className = 'result-item';

        const headerDiv = document.createElement('div');
        headerDiv.className = 'result-item__header flex-row';
        headerDiv.innerHTML = `
            <span class="result-item__header-title">${itemIndex}. ${escapeHtml(metric.source_file)}</span>
            <span class="result-item__header-stats">
                文字复制比: ${metric.ratio.toFixed(2)}% 
                (字面重复: ${metric.literal_char_count} 字符, ${metric.literal_hits} 处 | 语义相似: ${metric.semantic_hits} 处)
            </span>
        `;
        resultItemDiv.appendChild(headerDiv);

        const detailsDiv = document.createElement('div');
        detailsDiv.className = 'result-item__details flex-col';

        const literalHitsForSource = metric.all_hits_for_source.filter(h => h.match_type === 'literal');
        const semanticHitsForSource = metric.all_hits_for_source.filter(h => h.match_type === 'semantic');

        if (literalHitsForSource.length > 0) {
            detailsDiv.appendChild(createHitSection('字面重复片段', literalHitsForSource, 'literal'));
        }
        if (semanticHitsForSource.length > 0) {
            if (literalHitsForSource.length > 0) {
                const separator = document.createElement('hr');
                separator.className = 'result-item__section-separator';
                detailsDiv.appendChild(separator);
            }
            detailsDiv.appendChild(createHitSection('语义相似片段', semanticHitsForSource, 'semantic'));
        }

        resultItemDiv.appendChild(detailsDiv);
        resultsContainer.appendChild(resultItemDiv);
        itemIndex++;
    });
}

function createHitSection(title, hits, type) {
    const sectionDiv = document.createElement('div');
    sectionDiv.className = `result-item__section result-item__section--${type}`;
    sectionDiv.innerHTML = `<div class="result-item__section-header">${title} (${hits.length} 处)</div>`;

    const contentDiv = document.createElement('div');
    contentDiv.className = 'result-item__section-content';

    hits.forEach((hit, index) => {
        contentDiv.appendChild(createHitEntryElement(hit, index));
    });
    sectionDiv.appendChild(contentDiv);
    return sectionDiv;
}

function createHitEntryElement(hit, hitIndex) {
    const hitEntryDiv = document.createElement('div');
    hitEntryDiv.className = 'hit-entry'; // CSS from report_generator.py
    // hitEntryDiv.style.marginBottom = '15px'; ... (inline styles if needed)

    const fragType = hit.match_type || "未知类型";
    const inFrag = hit.input_fragment || {};
    const srcFrag = hit.source_fragment || {};
    const score = hit.similarity_score !== undefined ? hit.similarity_score : 0.0;
    const hitId = hit.hit_id || 'N/A';
    const sourceFile = hit.source_file || "未知来源"; // source_file应该在hit对象中

    const typeStr = fragType === "literal" ? "字面" : fragType === "semantic" ? "语义" : fragType.charAt(0).toUpperCase() + fragType.slice(1);
    const scoreStr = (typeof score === 'number' && score >= 0 && score <= 1 && fragType !== 'literal') ? `${(score * 100).toFixed(2)}%` : `${score.toFixed(4)}`;

    const infoLine = document.createElement('div');
    infoLine.className = 'hit-entry__info';
    infoLine.textContent = `片段 ${hitIndex + 1} [ID: ${hitId}] | 类型: ${typeStr} | 得分: ${scoreStr} | 来源: ${escapeHtml(sourceFile)}`;
    hitEntryDiv.appendChild(infoLine);

    const inputLine = createFragmentLine("原文片段: ", inFrag);
    hitEntryDiv.appendChild(inputLine);

    const sourceLine = createFragmentLine("对比来源: ", srcFrag);
    hitEntryDiv.appendChild(sourceLine);

    return hitEntryDiv;
}

function createFragmentLine(prefix, fragmentData) {
    const lineDiv = document.createElement('div');
    // lineDiv.className = 'hit-entry__input' or 'hit-entry__source'; // Set specific class if needed
    lineDiv.appendChild(document.createTextNode(prefix));

    const text = fragmentData.text;
    const start = fragmentData.start_char;
    const end = fragmentData.end_char;
    const len = fragmentData.length;
    const maxLength = 150; // Corresponds to REPORT_FRAGMENT_MAX_LENGTH

    if (text && typeof start === 'number') {
        const span = document.createElement('span');
        // span.className = 'hit-fragment hit-fragment--input/source';
        let displayText = escapeHtml(text.length > maxLength ? text.substring(0, maxLength) + '...' : text);
        span.innerHTML = displayText.replace(/\n/g, '<br>'); // Handle newlines
        lineDiv.appendChild(span);
        lineDiv.appendChild(document.createTextNode(` (位置: ${start}-${end}, 长度: ${len})`));
    } else {
        lineDiv.appendChild(document.createTextNode("N/A"));
    }
    return lineDiv;
}


function generateHighlightedTextHtml(cleanedText, hitDetailsBySource, highlightType) {
    if (!cleanedText) return '<p style="color:grey;">原文为空，无法高亮。</p>';

    const textLen = cleanedText.length;
    // Initialize tags: [tag_type (0=none, 1=literal, 2=semantic), hit_detail_object (optional)]
    let tags = Array(textLen).fill(null).map(() => [0, null]);
    const tagValue = highlightType === 'literal' ? 1 : 2;

    // Flatten and filter hits for the current type
    let allHitsOfType = [];
    for (const sourceFile in hitDetailsBySource) {
        if (Array.isArray(hitDetailsBySource[sourceFile])) {
            hitDetailsBySource[sourceFile].forEach(hit => {
                if (hit.match_type === highlightType) {
                    // Add source_file to hit object if not present, for consistency with report_generator.py
                    if (!hit.source_file) hit.source_file = sourceFile;
                    allHitsOfType.push(hit);
                }
            });
        }
    }
    // Sort by input fragment start position (important for correct layering if any, though not strictly needed for single-type highlight)
    allHitsOfType.sort((a, b) => (a.input_fragment.start_char || 0) - (b.input_fragment.start_char || 0));


    allHitsOfType.forEach(hit => {
        const inputFrag = hit.input_fragment;
        if (inputFrag && typeof inputFrag.start_char === 'number' && typeof inputFrag.end_char === 'number') {
            const start = Math.max(0, inputFrag.start_char);
            const end = Math.min(textLen, inputFrag.end_char);
            if (start < end) {
                for (let k = start; k < end; k++) {
                    // Later hits of the same type might overwrite, or you could merge/prioritize
                    tags[k] = [tagValue, hit];
                }
            }
        }
    });

    let htmlOutput = [];
    let currentTagType = 0;
    let inSpan = false;

    for (let idx = 0; idx < textLen; idx++) {
        const char = cleanedText[idx];
        const [tagType, hitDetail] = tags[idx]; // hitDetail not used in this simple version

        if (tagType !== currentTagType) {
            if (inSpan) {
                htmlOutput.push('</span>');
                inSpan = false;
            }
            currentTagType = tagType;
            if (currentTagType > 0) {
                inSpan = true;
                const cssClass = currentTagType === 1 ? "duplicate literal" : "duplicate semantic";
                htmlOutput.push(`<span class="${cssClass}">`);
            }
        }

        if (char === '\n') {
            if (inSpan) htmlOutput.push('</span>');
            htmlOutput.push('<br>\n');
            if (inSpan) { // Re-open span
                const cssClass = currentTagType === 1 ? "duplicate literal" : "duplicate semantic";
                htmlOutput.push(`<span class="${cssClass}">`);
            }
        } else if (char === '\r') {
            // ignore
        } else {
            htmlOutput.push(escapeHtml(char));
        }
    }

    if (inSpan) {
        htmlOutput.push('</span>');
    }
    return htmlOutput.join('');
}
